const text_bb_map = Dict(
    'A' => '𝔸',
    'B' => '𝔹',
    'C' => 'ℂ',
    'D' => '𝔻',
    'E' => '𝔼',
    'F' => '𝔽',
    'G' => '𝔾',
    'H' => 'ℍ',
    'I' => '𝕀',
    'J' => '𝕁',
    'K' => '𝕂',
    'L' => '𝕃',
    'M' => '𝕄',
    'N' => 'ℕ',
    'O' => '𝕆',
    'P' => 'ℙ',
    'Q' => 'ℚ',
    'R' => 'ℝ',
    'S' => '𝕊',
    'T' => '𝕋',
    'U' => '𝕌',
    'V' => '𝕍',
    'W' => '𝕎',
    'X' => '𝕏',
    'Y' => '𝕐',
    'Z' => 'ℤ',
    'a' => '𝕒',
    'b' => '𝕓',
    'c' => '𝕔',
    'd' => '𝕕',
    'e' => '𝕖',
    'f' => '𝕗',
    'g' => '𝕘',
    'h' => '𝕙',
    'i' => '𝕚',
    'j' => '𝕛',
    'k' => '𝕜',
    'l' => '𝕝',
    'm' => '𝕞',
    'n' => '𝕟',
    'o' => '𝕠',
    'p' => '𝕡',
    'q' => '𝕢',
    'r' => '𝕣',
    's' => '𝕤',
    't' => '𝕥',
    'u' => '𝕦',
    'v' => '𝕧',
    'w' => '𝕨',
    'x' => '𝕩',
    'y' => '𝕪',
    'z' => '𝕫',
    '0' => '𝟘',
    '1' => '𝟙',
    '2' => '𝟚',
    '3' => '𝟛',
    '4' => '𝟜',
    '5' => '𝟝',
    '6' => '𝟞',
    '7' => '𝟟',
    '8' => '𝟠',
    '9' => '𝟡'
)

const text_it_map = Dict(
    'A' => '𝐴',
    'B' => '𝐵',
    'C' => '𝐶',
    'D' => '𝐷',
    'E' => '𝐸',
    'F' => '𝐹',
    'G' => '𝐺',
    'H' => '𝐻',
    'I' => '𝐼',
    'J' => '𝐽',
    'K' => '𝐾',
    'L' => '𝐿',
    'M' => '𝑀',
    'N' => '𝑁',
    'O' => '𝑂',
    'P' => '𝑃',
    'Q' => '𝑄',
    'R' => '𝑅',
    'S' => '𝑆',
    'T' => '𝑇',
    'U' => '𝑈',
    'V' => '𝑉',
    'W' => '𝑊',
    'X' => '𝑋',
    'Y' => '𝑌',
    'Z' => '𝑍',
    'a' => '𝑎',
    'b' => '𝑏',
    'c' => '𝑐',
    'd' => '𝑑',
    'e' => '𝑒',
    'f' => '𝑓',
    'g' => '𝑔',
    'h' => 'ℎ',
    'i' => '𝑖',
    'j' => '𝑗',
    'k' => '𝑘',
    'l' => '𝑙',
    'm' => '𝑚',
    'n' => '𝑛',
    'o' => '𝑜',
    'p' => '𝑝',
    'q' => '𝑞',
    'r' => '𝑟',
    's' => '𝑠',
    't' => '𝑡',
    'u' => '𝑢',
    'v' => '𝑣',
    'w' => '𝑤',
    'x' => '𝑥',
    'y' => '𝑦',
    'z' => '𝑧',
    'Α' => '𝛢',
    'Β' => '𝛣',
    'Γ' => '𝛤',
    'Δ' => '𝛥',
    'Ε' => '𝛦',
    'Ζ' => '𝛧',
    'Η' => '𝛨',
    'Θ' => '𝛩',
    'Ι' => '𝛪',
    'Κ' => '𝛫',
    'Λ' => '𝛬',
    'Μ' => '𝛭',
    'Ν' => '𝛮',
    'Ξ' => '𝛯',
    'Ο' => '𝛰',
    'Π' => '𝛱',
    'Ρ' => '𝛲',
    'ϴ' => '𝛳',
    'Σ' => '𝛴',
    'Τ' => '𝛵',
    'Υ' => '𝛶',
    'Φ' => '𝛷',
    'Χ' => '𝛸',
    'Ψ' => '𝛹',
    'Ω' => '𝛺',
    '∇' => '𝛻',
    'α' => '𝛼',
    'β' => '𝛽',
    'γ' => '𝛾',
    'δ' => '𝛿',
    'ε' => '𝜀',
    'ζ' => '𝜁',
    'η' => '𝜂',
    'θ' => '𝜃',
    'ι' => '𝜄',
    'κ' => '𝜅',
    'λ' => '𝜆',
    'μ' => '𝜇',
    'ν' => '𝜈',
    'ξ' => '𝜉',
    'ο' => '𝜊',
    'π' => '𝜋',
    'ρ' => '𝜌',
    'ς' => '𝜍',
    'σ' => '𝜎',
    'τ' => '𝜏',
    'υ' => '𝜐',
    'φ' => '𝜑',
    'χ' => '𝜒',
    'ψ' => '𝜓',
    'ω' => '𝜔',
    '∂' => '𝜕',
    'ϵ' => '𝜖',
    'ϑ' => '𝜗',
    'ϰ' => '𝜘',
    'ϕ' => '𝜙',
    'ϱ' => '𝜚',
    'ϖ' => '𝜛'
)


const text_bf_map = Dict(
    'A' => '𝐀',
    'B' => '𝐁',
    'C' => '𝐂',
    'D' => '𝐃',
    'E' => '𝐄',
    'F' => '𝐅',
    'G' => '𝐆',
    'H' => '𝐇',
    'I' => '𝐈',
    'J' => '𝐉',
    'K' => '𝐊',
    'L' => '𝐋',
    'M' => '𝐌',
    'N' => '𝐍',
    'O' => '𝐎',
    'P' => '𝐏',
    'Q' => '𝐐',
    'R' => '𝐑',
    'S' => '𝐒',
    'T' => '𝐓',
    'U' => '𝐔',
    'V' => '𝐕',
    'W' => '𝐖',
    'X' => '𝐗',
    'Y' => '𝐘',
    'Z' => '𝐙',
    'a' => '𝐚',
    'b' => '𝐛',
    'c' => '𝐜',
    'd' => '𝐝',
    'e' => '𝐞',
    'f' => '𝐟',
    'g' => '𝐠',
    'h' => '𝐡',
    'i' => '𝐢',
    'j' => '𝐣',
    'k' => '𝐤',
    'l' => '𝐥',
    'm' => '𝐦',
    'n' => '𝐧',
    'o' => '𝐨',
    'p' => '𝐩',
    'q' => '𝐪',
    'r' => '𝐫',
    's' => '𝐬',
    't' => '𝐭',
    'u' => '𝐮',
    'v' => '𝐯',
    'w' => '𝐰',
    'x' => '𝐱',
    'y' => '𝐲',
    'z' => '𝐳',
    'Α' => '𝚨',
    'Β' => '𝚩',
    'Γ' => '𝚪',
    'Δ' => '𝚫',
    'Ε' => '𝚬',
    'Ζ' => '𝚭',
    'Η' => '𝚮',
    'Θ' => '𝚯',
    'Ι' => '𝚰',
    'Κ' => '𝚱',
    'Λ' => '𝚲',
    'Μ' => '𝚳',
    'Ν' => '𝚴',
    'Ξ' => '𝚵',
    'Ο' => '𝚶',
    'Π' => '𝚷',
    'Ρ' => '𝚸',
    'ϴ' => '𝚹',
    'Σ' => '𝚺',
    'Τ' => '𝚻',
    'Υ' => '𝚼',
    'Φ' => '𝚽',
    'Χ' => '𝚾',
    'Ψ' => '𝚿',
    'Ω' => '𝛀',
    '∇' => '𝛁',
    'α' => '𝛂',
    'β' => '𝛃',
    'γ' => '𝛄',
    'δ' => '𝛅',
    'ε' => '𝛆',
    'ζ' => '𝛇',
    'η' => '𝛈',
    'θ' => '𝛉',
    'ι' => '𝛊',
    'κ' => '𝛋',
    'λ' => '𝛌',
    'μ' => '𝛍',
    'ν' => '𝛎',
    'ξ' => '𝛏',
    'ο' => '𝛐',
    'π' => '𝛑',
    'ρ' => '𝛒',
    'ς' => '𝛓',
    'σ' => '𝛔',
    'τ' => '𝛕',
    'υ' => '𝛖',
    'φ' => '𝛗',
    'χ' => '𝛘',
    'ψ' => '𝛙',
    'ω' => '𝛚',
    '∂' => '𝛛',
    'ϵ' => '𝛜',
    'ϑ' => '𝛝',
    'ϰ' => '𝛞',
    'ϕ' => '𝛟',
    'ϱ' => '𝛠',
    'ϖ' => '𝛡',
    '0' => '𝟎',
    '1' => '𝟏',
    '2' => '𝟐',
    '3' => '𝟑',
    '4' => '𝟒',
    '5' => '𝟓',
    '6' => '𝟔',
    '7' => '𝟕',
    '8' => '𝟖',
    '9' => '𝟗'
)

const text_frak_map = Dict(
    'A' => '𝔄',
    'B' => '𝔅',
    'C' => 'ℭ',
    'D' => '𝔇',
    'E' => '𝔈',
    'F' => '𝔉',
    'G' => '𝔊',
    'H' => 'ℌ',
    'I' => 'ℑ',
    'J' => '𝔍',
    'K' => '𝔎',
    'L' => '𝔏',
    'M' => '𝔐',
    'N' => '𝔑',
    'O' => '𝔒',
    'P' => '𝔓',
    'Q' => '𝔔',
    'R' => 'ℜ',
    'S' => '𝔖',
    'T' => '𝔗',
    'U' => '𝔘',
    'V' => '𝔙',
    'W' => '𝔚',
    'X' => '𝔛',
    'Y' => '𝔜',
    'Z' => 'ℨ',
    'a' => '𝔞',
    'b' => '𝔟',
    'c' => '𝔠',
    'd' => '𝔡',
    'e' => '𝔢',
    'f' => '𝔣',
    'g' => '𝔤',
    'h' => '𝔥',
    'i' => '𝔦',
    'j' => '𝔧',
    'k' => '𝔨',
    'l' => '𝔩',
    'm' => '𝔪',
    'n' => '𝔫',
    'o' => '𝔬',
    'p' => '𝔭',
    'q' => '𝔮',
    'r' => '𝔯',
    's' => '𝔰',
    't' => '𝔱',
    'u' => '𝔲',
    'v' => '𝔳',
    'w' => '𝔴',
    'x' => '𝔵',
    'y' => '𝔶',
    'z' => '𝔷'
)

const text_cal_map = Dict(
    'A' => '𝓐',
    'B' => '𝓑',
    'C' => '𝓒',
    'D' => '𝓓',
    'E' => '𝓔',
    'F' => '𝓕',
    'G' => '𝓖',
    'H' => '𝓗',
    'I' => '𝓘',
    'J' => '𝓙',
    'K' => '𝓚',
    'L' => '𝓛',
    'M' => '𝓜',
    'N' => '𝓝',
    'O' => '𝓞',
    'P' => '𝓟',
    'Q' => '𝓠',
    'R' => '𝓡',
    'S' => '𝓢',
    'T' => '𝓣',
    'U' => '𝓤',
    'V' => '𝓥',
    'W' => '𝓦',
    'X' => '𝓧',
    'Y' => '𝓨',
    'Z' => '𝓩',
    'a' => '𝓪',
    'b' => '𝓫',
    'c' => '𝓬',
    'd' => '𝓭',
    'e' => '𝓮',
    'f' => '𝓯',
    'g' => '𝓰',
    'h' => '𝓱',
    'i' => '𝓲',
    'j' => '𝓳',
    'k' => '𝓴',
    'l' => '𝓵',
    'm' => '𝓶',
    'n' => '𝓷',
    'o' => '𝓸',
    'p' => '𝓹',
    'q' => '𝓺',
    'r' => '𝓻',
    's' => '𝓼',
    't' => '𝓽',
    'u' => '𝓾',
    'v' => '𝓿',
    'w' => '𝔀',
    'x' => '𝔁',
    'y' => '𝔂',
    'z' => '𝔃'
)

const text_mono_map = Dict(
    'A' => '𝙰',
    'B' => '𝙱',
    'C' => '𝙲',
    'D' => '𝙳',
    'E' => '𝙴',
    'F' => '𝙵',
    'G' => '𝙶',
    'H' => '𝙷',
    'I' => '𝙸',
    'J' => '𝙹',
    'K' => '𝙺',
    'L' => '𝙻',
    'M' => '𝙼',
    'N' => '𝙽',
    'O' => '𝙾',
    'P' => '𝙿',
    'Q' => '𝚀',
    'R' => '𝚁',
    'S' => '𝚂',
    'T' => '𝚃',
    'U' => '𝚄',
    'V' => '𝚅',
    'W' => '𝚆',
    'X' => '𝚇',
    'Y' => '𝚈',
    'Z' => '𝚉',
    'a' => '𝚊',
    'b' => '𝚋',
    'c' => '𝚌',
    'd' => '𝚍',
    'e' => '𝚎',
    'f' => '𝚏',
    'g' => '𝚐',
    'h' => '𝚑',
    'i' => '𝚒',
    'j' => '𝚓',
    'k' => '𝚔',
    'l' => '𝚕',
    'm' => '𝚖',
    'n' => '𝚗',
    'o' => '𝚘',
    'p' => '𝚙',
    'q' => '𝚚',
    'r' => '𝚛',
    's' => '𝚜',
    't' => '𝚝',
    'u' => '𝚞',
    'v' => '𝚟',
    'w' => '𝚠',
    'x' => '𝚡',
    'y' => '𝚢',
    'z' => '𝚣',
    '0' => '𝟶',
    '1' => '𝟷',
    '2' => '𝟸',
    '3' => '𝟹',
    '4' => '𝟺',
    '5' => '𝟻',
    '6' => '𝟼',
    '7' => '𝟽',
    '8' => '𝟾',
    '9' => '𝟿'
)



for (f, map) in (
        :to_blackboardbold => :text_bb_map,
        :to_boldface => :text_bf_map,
        :to_italic => :text_it_map,
        :to_caligraphic => :text_cal_map,
        :to_frakture => :text_frak_map,
        :to_mono => :text_mono_map,
    )
    @eval begin
        $f(x::Char) = get($map, x, x) # default to same char to keep errors down
        $f(io::IO, x::Char) = print(io, $f(x))
        $f(io::IO, x::AbstractString) = for char in x
            print(io, $f(char))
        end
        $f(x::AbstractString) = sprint() do io
            $f(io, x)
        end
    end
end
"""
Underlines a text
"""
function to_underline(x::AbstractString)
    sprint() do io
        to_underline(io, x)
    end
end
function to_underline(io::IO, x::Char)
    print(io, x, Char(0x0332))
end
function to_underline(io::IO, x::AbstractString)
    for c in x
        to_underline(io, c)
    end
end

"""
Overlines a text
"""
function to_overline(x::AbstractString)
    sprint() do io
        to_overline(io, x)
    end
end
function to_overline(io::IO, x::Char)
    print(io, x, Char(0x0305))
end
function to_overline(io::IO, x::AbstractString)
    for c in x
        to_overline(io, c)
    end
end
